package com.gzc.just.play.last.war.common.inventory;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Inventory manager
 */
@Component
public class InventoryManager {
    
    private static final Logger log = LoggerFactory.getLogger(InventoryManager.class);
    
    // Player inventory cache
    private final ConcurrentHashMap<Long, Map<Long, Item>> playerInventories = new ConcurrentHashMap<>();

    /**
     * Get player inventory
     * @param playerId Player ID
     * @return Inventory item mapping
     */
    public Map<Long, Item> getPlayerInventory(Long playerId) {
        return playerInventories.computeIfAbsent(playerId, id -> new ConcurrentHashMap<>());
    }

    /**
     * Add item to inventory
     * @param playerId Player ID
     * @param item Item object
     * @return Whether addition succeeded
     */
    public boolean addItem(Long playerId, Item item) {
        Map<Long, Item> inventory = getPlayerInventory(playerId);
        
        // Check if inventory has space
        if (inventory.size() >= getMaxInventorySize()) {
            log.warn("Player {} inventory is full, cannot add item {}", playerId, item.getId());
            return false;
        }
        
        // Check if item already exists
        if (inventory.containsKey(item.getId())) {
            // Stack items
            Item existingItem = inventory.get(item.getId());
            if (existingItem.canStack(item)) {
                existingItem.setCount(existingItem.getCount() + item.getCount());
                log.info("Stacked item {} for player {}, new count: {}", 
                        item.getId(), playerId, existingItem.getCount());
                return true;
            } else {
                log.warn("Player {} already has non-stackable item {}", playerId, item.getId());
                return false;
            }
        } else {
            inventory.put(item.getId(), item);
            log.info("Added item {} to player {} inventory, count: {}", 
                     item.getId(), playerId, item.getCount());
            return true;
        }
    }
    
    /**
     * Remove item from inventory
     * @param playerId Player ID
     * @param itemId Item ID
     * @param count Quantity to remove
     * @return Whether removal succeeded
     */
    public boolean removeItem(Long playerId, Long itemId, int count) {
        Map<Long, Item> inventory = getPlayerInventory(playerId);
        Item item = inventory.get(itemId);
        
        if (item != null && item.getCount() >= count) {
            item.setCount(item.getCount() - count);
            
            if (item.getCount() == 0) {
                inventory.remove(itemId);
            }
            
            log.info("Removed {} of item {} from player {} inventory, remaining: {}", 
                     count, itemId, playerId, item.getCount());
            return true;
        }
        
        log.warn("Player {} does not have enough of item {}: {}", playerId, itemId, count);
        return false;
    }
    
    /**
     * Use item
     * @param playerId Player ID
     * @param itemId Item ID
     * @param quantity Item quantity
     * @param targetId Target ID
     * @return Whether use succeeded
     */
    public boolean useItem(Long playerId, Long itemId, Integer quantity, Long targetId) {
        Map<Long, Item> inventory = getPlayerInventory(playerId);
        Item item = inventory.get(itemId);
        
        if (item != null && item.getCount() >= quantity) {
            // Simple item usage logic
            log.info("Player {} used item {} (quantity: {}) on target {}", 
                     playerId, itemId, quantity, targetId);
            
            // Reduce item count
            item.setCount(item.getCount() - quantity);
            
            if (item.getCount() == 0) {
                inventory.remove(itemId);
            }
            
            return true;
        }
        
        log.warn("Player {} does not have enough of item {}: {}", playerId, itemId, quantity);
        return false;
    }
    
    /**
     * Check if has enough items
     * @param playerId Player ID
     * @param itemId Item ID
     * @param count Required quantity
     * @return Whether has enough items
     */
    public boolean hasItem(Long playerId, Long itemId, int count) {
        Map<Long, Item> inventory = getPlayerInventory(playerId);
        Item item = inventory.get(itemId);
        return item != null && item.getCount() >= count;
    }
    
    /**
     * Get inventory max size
     * @return Inventory max size
     */
    private int getMaxInventorySize() {
        return 100; // Default inventory size
    }
    
    /**
     * Item entity class
     */
    public static class Item {
        private final Long id;
        private final String name;
        private final Integer stackLimit;
        private int count;
        
        public Item(Long id, String name, int count, Integer stackLimit) {
            this.id = id;
            this.name = name;
            this.count = count;
            this.stackLimit = stackLimit != null ? stackLimit : 999;
        }
        
        public Long getId() {
            return id;
        }
        
        public String getName() {
            return name;
        }
        
        public int getCount() {
            return count;
        }
        
        public void setCount(int count) {
            this.count = Math.max(0, count);
        }
        
        public Integer getStackLimit() {
            return stackLimit;
        }
        
        /**
         * Check if can stack with another item
         * @param other Another item
         * @return Whether can stack
         */
        public boolean canStack(Item other) {
            return id.equals(other.getId()) && (count + other.getCount()) <= stackLimit;
        }
    }
}